/* **********************************************************************
版本: 2022.3.28f1
作者: wzz
日期: 2025-7-14
描述: 格式化对象，如：list, dictionary 格式化成字符串输出
      特别注意：使用时可能发生大量装箱，建义只作调试输出使用
***********************************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public static class FormatObj
{
    /// <summary>
    /// 换行输出
    /// </summary>
    public static bool WrappingLines { get; set; } = true;

    /// <summary>
    /// 控制开关，为false时，输出空字符
    /// </summary>
    public static bool Enable { get; set; } = true;

    private static int wrappingLinesNum = 0;
    private static StringBuilder stringBuilder = new StringBuilder();

    /// <summary>
    /// 格式化对象，如：list, dictionary 格式化成字符串输出
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static string ToString(Object obj)
    {
        if (!Enable)
            return string.Empty;

        stringBuilder.Clear();
        wrappingLinesNum = 0;

        if (IsDictionary(obj))
        {
            AppendLine();
            ToDicString(stringBuilder, obj);
            AppendLine();
        }
        else if (IsIEnumerable(obj))
        {
            AppendLine();
            ToListString(stringBuilder, obj);
            AppendLine();
        }
        else
        {
            stringBuilder.Append(ToStringObj(obj));
        }
        return stringBuilder.ToString();
    }

    private static void ToListString(StringBuilder stringBuilder, Object obj)
    {
        var tab = obj as IEnumerable;
        Append("{");
        wrappingLinesNum++;
        var list = tab.Cast<object>().ToList();
        for (int i = 0; i < list.Count; i++)
        {
            AppendLine();
            if (IsIEnumerable(list[i]))
            {
                ToListString(stringBuilder, list[i]);
            }
            else
            {
                if (IsStringOrChar(list[i]))
                {
                    Append("\"" + ToStringObj(list[i]) + "\"");
                }
                else
                {
                    Append(ToStringObj(list[i]));
                }
            }
            if (i == list.Count - 1)
                AppendLine();
            else
                Append(",", false);
        }

        wrappingLinesNum--;
        Append("}");
    }

    private static void ToDicString(StringBuilder stringBuilder, Object obj)
    {
        var map = obj as IDictionary;

        Append("{");
        wrappingLinesNum++;

        var list = map.Keys.Cast<Object>().ToList();
        for (int i = 0; i < list.Count; i++)
        {
            var key = list[i];
            var value = map[key];

            AppendLine();

            if (IsStringOrChar(key))
            {
                Append("[\"" + ToStringObj(key) + "\"]:");
            }
            else
            {
                Append("[" + ToStringObj(key) + "]:");
            }

            if (IsDictionary(value))
            {
                AppendLine();
                ToDicString(stringBuilder, value);
            }
            else if (IsIEnumerable(value))
            {
                AppendLine();
                ToListString(stringBuilder, value);
            }
            else if (IsStringOrChar(value))
            {
                Append("\"" + ToStringObj(value) + "\"", false);
            }
            else
            {
                Append(ToStringObj(value), false);
            }

            if (i == list.Count - 1)
                AppendLine();
            else
                Append(",", false);
        }

        wrappingLinesNum--;
        Append("}");
    }

    /// <summary>
    /// 添加字符
    /// </summary>
    /// <param name="str"></param>
    private static void Append(string str, bool wrap = true)
    {
        if (WrappingLines && wrap)
        {
            for (int i = 0; i < wrappingLinesNum; i++)
            {
                stringBuilder.Append("    ");
            }
        }

        stringBuilder.Append(str);
    }

    /// <summary>
    /// 添加换行
    /// </summary>
    /// <param name="wrap"></param>
    private static void AppendLine(bool wrap = true)
    {
        if (WrappingLines && wrap)
        {
            stringBuilder.AppendLine();
        }
    }

    /// <summary>
    /// 判断是否是枚举
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static bool IsEnum(Object obj)
    {
        return obj is Enum && !(obj is null);
    }

    /// <summary>
    /// 判断是否是字典
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static bool IsDictionary(Object obj)
    {
        return obj is System.Collections.IDictionary && !(obj is null);
    }

    /// <summary>
    /// 判断是否为可使用 foreach 遍历对象
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static bool IsIEnumerable(Object obj)
    {
        return !(obj is string) && obj is IEnumerable && !(obj is null);
    }

    /// <summary>
    /// 判断是否为字符或字符串
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static bool IsStringOrChar(Object obj)
    {
        return obj is string || obj is char;
    }

    /// <summary>
    /// 将对象转成字符串
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static string ToStringObj(Object obj)
    {
        if (obj == null)
            return "null";
        return obj.ToString();
    }

    /// <summary>
    /// 测试例子
    /// </summary>
    public static string TestExample()
    {
        StringBuilder stringBuilder = new StringBuilder();

        stringBuilder.AppendLine();
        stringBuilder.AppendLine("测试用例：");
        stringBuilder.AppendLine("false：" + ToString(false));
        stringBuilder.AppendLine("null：" + ToString(null));
        stringBuilder.AppendLine("int：" + ToString(10));
        stringBuilder.AppendLine("float：" + ToString(10.66f));

        int[] Array1 = { 1, 2, 3 };
        stringBuilder.AppendLine("类型int[]：" + ToString(Array1));

        string[] Array2 = { "wzz", "is", "men" };
        stringBuilder.AppendLine("类型string[]：" + ToString(Array2));

        char[] Array3 = { 'c', 'h', 'c', 'r' };
        stringBuilder.AppendLine("类型char[]：" + ToString(Array3));

        List<int> list1 = new List<int>() { 4, 5, 6 };
        stringBuilder.AppendLine("类型List<int>：" + ToString(list1));

        List<string> list2 = new List<string>() { "this", "is", "string" };
        stringBuilder.AppendLine("类型List<string>：" + ToString(list2));

        List<List<int>> list11 = new List<List<int>>();
        list11.Add(Array1.ToList());
        list11.Add(null);
        list11.Add(list1);
        stringBuilder.AppendLine("类型List<List<int>>：" + ToString(list11));

        Dictionary<int, string> map1 = new Dictionary<int, string>();
        map1.Add(1, "a");
        map1.Add(200, "d");
        stringBuilder.AppendLine("类型Dictionary<int, string>：" + ToString(map1));

        Dictionary<int, List<int>> map2 = new Dictionary<int, List<int>>();
        map2.Add(100, Array1.ToList());
        map2.Add(200, list1);
        stringBuilder.AppendLine("类型Dictionary<int, List<int>>：" + ToString(map2));

        Dictionary<string, List<string>> map3 = new Dictionary<string, List<string>>();
        map3.Add("a1", list2);
        map3.Add("a2", Array2.ToList());
        stringBuilder.AppendLine("类型Dictionary<string, List<string>>：" + ToString(map3));

        Dictionary<int, Dictionary<string, List<string>>> map4 = new Dictionary<int, Dictionary<string, List<string>>>();
        map4.Add(999, map3);
        stringBuilder.AppendLine("类型Dictionary<int, Dictionary<string, List<string>>>：" + ToString(map4));

        return stringBuilder.ToString();
    }
}